home *** CD-ROM | disk | FTP | other *** search
- TITLE LC Interrupt trap routine
- NAME LCINT
- INCLUDE DOS.MAC ; BE SURE TO INCLUDE THE CORRECT
- ; DOS.MAC!!
-
- ;****************************************************************************
- ;
- ; This is the heart of a C driven interrupt handler. This file was used to
- ; write a critical error handler that remained resident. (It replaced the
- ; "Abort, Retry, Ignore" prompt with a window.) This file can be adapted to
- ; any interrupt and any C routine with a little work. THIS HAS BEEN USED ONLY
- ; IN THE S MODEL.
- ;
- ; REVISION HISTORY:
- ;
- ; 7/19/87 Thomas A. Lundin
- ; Graphics Unlimited Inc.
- ; 3000 Second St. No.
- ; Minneapolis, MN 55411
- ; (612) 588-7571
- ;
- ; Implemented DOS stack save/restore for a more stable exit from & reentry to
- ; the original DOS environment which called us.
- ;
- ; 8/4/87 TAL again
- ;
- ; Now try the keyboard interrupt vector. Also added some routines (but did
- ; not activate them here) which save/restore the caller's PSP and DTA. Why?
- ; I had some silly notion that it might help my TSR program from bombing when
- ; issuing DOS calls when other DOS calls are in process. Hah! I should have
- ; known better. But I left them in, in case you are interested. The kludge I
- ; ended up with checks the DOS "Critical Section Flag" and disables any calls
- ; to DOS when other calls are in process. That section of code has also been
- ; commented out. Also made some changes to my 7/19/87 modifications.
- ;****************************************************************************
-
- DOS_INT EQU 16H ; int to be replaced (keyboard)
-
- WRITE_INT EQU 25H ; DOS write int vector
- READ_INT EQU 35H ; DOS read int vector
- ;******************************************************************************
- HOTKEY EQU 1300H ; ALT-R here - can be anything you want
- ;******************************************************************************
- STAK_LEN EQU 800H ; size of stack area to save ;;;;;;;;;;
-
-
- XREG STRUC
- REG_AX DW ? ; general purpose registers
- REG_BX DW ?
- REG_CX DW ?
- REG_DX DW ?
- REG_SI DW ?
- REG_DI DW ?
- XREG ENDS
-
- SREGS STRUC
- REG_ES DW ? ; segment registers
- REG_CS DW ?
- REG_SS DW ?
- REG_DS DW ?
- SREGS ENDS
-
- DSEG
-
- INT_REGS XREG <> ; saved regs. at int time
- INT_SEGREGS SREGS <> ; saved seg. regs.
- EXTRN _TOP:WORD ; declared by C.ASM -- points
- ; to top of stack
- EXTRN _STACK:WORD ; size of stack
- PUBLIC _INDOS ; if _INDOS is non-zero...
- _INDOS DW 0 ; ...then don't interrupt DOS
- ENDDS
-
- EXTRN INTTIME:NEAR ; your int routine goes here!
-
- PSEG
- ;;
- ; interrupt time data storage
- ;;
- C_ENVIRONMENT_DS DW ? ; filled by int init, used...
- C_ENVIRONMENT_ES DW ? ; ...to recreate C environment
- C_ENVIRONMENT_SS DW ?
- C_ENVIRONMENT_SP DW ?
-
- INT_TIME_ES DW ?
- INT_TIME_DS DW ? ; temp save of DS at int time
- INT_TIME_SI DW ? ; temp save of SI at int time
-
- INT_TIME_BP DW ? ; added to account for no BP or SP...
- INT_TIME_SP DW ? ; ...in above structures
-
- RETURN_VALUE DW ? ; return value from C service routine
-
- DOS_SERVICE DD ? ; address of DOS Service routine
- INT_TWOONE DD ? ; old INT 21 vector
-
- INT_IN_PROGRESS DB 0 ; interrupt in progress flag
-
- CALSTK DB STAK_LEN DUP(?) ;caller's stack save area ;;;;;;;;;;;;;;;;;;;;;
- STKSEG DW ? ;which stack segment ;;;;;;;;;;;;;;;;;;;;;;;;;;
- FLAGS DW ? ;caller's flags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;DOSDTA DD ? ;caller's DTA
- ;C_DTA DD ? ;C's DTA
- ;DOSPSP DW ? ;caller's PSP
- ;C_PSP DW ? ;C's PSP
- ;;**************************************************************************
- ; name LC_SERVICE_INT
- ;
- ; description Entered at (software) interrupt time, this routine
- ; restores the C enviroment and processes the interrupt
- ; trapping all references to the quad file
- ;;
-
- IF LPROG
- LC_SERVICE_INT PROC FAR
- ELSE
- LC_SERVICE_INT PROC NEAR
- ENDIF
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; This section of code can be commented out if you don't wish to trap the
- ; keyboard interrupt. Remember, then, to change the DOS_INT EQUate to whatever
- ; interrupt it is you DO want to trap.
-
- CMP CS:INT_IN_PROGRESS,1 ; already in this interrupt?
- JNE FIRST_TIME ; no, check the key
- EXIT16:
- JMP DWORD PTR CS:DOS_SERVICE ; else forget it
-
- FIRST_TIME:
- CMP AH,0 ; is this character request
- JNE EXIT16 ; no, exit immediately
- PUSHF
- CALL DWORD PTR CS:DOS_SERVICE ; get the next character from buffer
- CMP AX,HOTKEY ; is it the hot key?
- JE HOT_HIT ; yes, dive into the interrupt
- IRET ; no, send the char back to caller
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- HOT_HIT:
- MOV CS:INT_IN_PROGRESS,1 ; set int in progress flag
-
- MOV CS:INT_TIME_ES,ES ; save ES so it can be overwritten
- MOV CS:INT_TIME_DS,DS ; save DS so it can be overwritten
- MOV CS:INT_TIME_SI,SI ; save SI so it can be overwritten
- MOV CS:INT_TIME_BP,BP ; save BP as structs do not have it
- MOV CS:INT_TIME_SP,SP ; save SP as structs do not have it
- MOV DS,CS:C_ENVIRONMENT_DS ; set up C enviroment
- MOV SI,OFFSET INT_REGS ; point to input regs struct
-
- MOV DS:[SI].REG_AX,AX ; save general purpose regs
- MOV DS:[SI].REG_BX,BX
- MOV DS:[SI].REG_CX,CX
- MOV DS:[SI].REG_DX,DX
- MOV DS:[SI].REG_DI,DI
- MOV AX,CS:INT_TIME_SI ; SI has been overwritten
- MOV DS:[SI].REG_SI,AX
-
- MOV SI,OFFSET INT_SEGREGS ; point to input segment regs struct
-
- MOV AX,CS:INT_TIME_ES ; ES has been overwritten
- MOV DS:[SI].REG_ES,AX
- MOV DS:[SI].REG_SS,SS
- MOV AX,CS:INT_TIME_DS ; DS has been overwritten
- MOV DS:[SI].REG_DS,AX
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- PUSHF
- POP AX
- MOV CS:FLAGS,AX ;save caller's flags
- MOV SI,SS
- MOV WORD PTR CS:STKSEG,SI ;save caller's stack segment
- PUSH DS
- CLI
- MOV AX,CS ;save area address
- MOV ES,AX
- MOV AX,WORD PTR CS:STKSEG ;caller's stack address
- MOV DS,AX
- MOV SI,0 ;stack offset
- MOV DI,OFFSET CS:CALSTK
- MOV CX,STAK_LEN ;length to save
- CLD
- REP MOVSB ;save caller's stack
- STI
- ;........................................
- ; MOV AX,2F00H ;get caller's DTA
- ; INT 21H
- ; MOV WORD PTR CS:DOSDTA+2,ES ;save it
- ; MOV WORD PTR CS:DOSDTA,BX
- ;
- ; MOV AX,5100H ;get caller's PSP
- ; INT 21H
- ; MOV CS:DOSPSP,BX ;save it
- ;
- ; MOV AX,1A00H ;set C's DTA
- ; MOV DX,WORD PTR CS:C_DTA
- ; MOV DS,WORD PTR CS:C_DTA+2
- ; INT 21H
- ;
- ; MOV BX,CS:C_PSP
- ; MOV AX,5000H ;set C's PSP
- ; INT 21H
- ;........................................
- POP DS
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- MOV ES,CS:C_ENVIRONMENT_ES ; complete C environment
- MOV SS,CS:C_ENVIRONMENT_SS
- MOV SP,CS:C_ENVIRONMENT_SP
- ;----------------------------------------
- ; PUSH ES ;
- ; PUSH BX ;
- ; PUSH AX ;
- ; MOV AX,3400H ; the "Critical Section Flag"
- ; INT 21H ; determines DOS interruptability
- ; MOV AL,BYTE PTR ES:[BX] ;
- ; MOV BYTE PTR CS:_INDOS,AL ; save it for INTTIME
- ; POP AX ;
- ; POP BX ;
- ; POP ES ;
- ;----------------------------------------
-
- CALL INTTIME ; call the C routine
-
- MOV CS:RETURN_VALUE,AX ; save return value
- XOR AX,AX
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- PUSH DS
- ;........................................
- ; MOV AX,1A00H ;reinstate DOS DTA
- ; MOV DX,WORD PTR CS:DOSDTA
- ; MOV DS,WORD PTR CS:DOSDTA+2
- ; INT 21H
- ;
- ; MOV BX,CS:DOSPSP
- ; MOV AX,5000H ;and DOS PSP
- ; INT 21H
- ;........................................
- CLI
- MOV AX,WORD PTR CS:STKSEG ;restore caller's stack area
- MOV ES,AX
- MOV DI,0 ;restore data areas
- MOV AX,CS
- MOV DS,AX
- MOV SI,OFFSET CS:CALSTK
- MOV CX,STAK_LEN ;length to restore
- CLD
- REP MOVSB ;copy stack data
- STI
- POP DS
-
- MOV AX,CS:FLAGS
- PUSH AX
- POPF ;restore caller's flags
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- MOV SI,OFFSET INT_REGS ; point to input regs struct
-
- MOV AX,DS:[SI].REG_SI ; SI needs to be saved while used
- MOV CS:INT_TIME_SI,AX
-
- MOV AX,DS:[SI].REG_AX ; restore general purpose regs
- MOV BX,DS:[SI].REG_BX
- MOV CX,DS:[SI].REG_CX
- MOV DX,DS:[SI].REG_DX
- MOV DI,DS:[SI].REG_DI
-
- MOV SI,OFFSET INT_SEGREGS ; point to input segment regs struct
-
- MOV ES,DS:[SI].REG_DS ; DS needs to be saved while used
- MOV CS:INT_TIME_DS,ES
-
- MOV ES,DS:[SI].REG_ES
- MOV SS,DS:[SI].REG_SS
-
- MOV SI,CS:INT_TIME_SI ; restore pointing registers
- MOV DS,CS:INT_TIME_DS
-
- MOV BP,CS:INT_TIME_BP ; special BP restore
- MOV SP,CS:INT_TIME_SP ; special SP restore
-
- MOV CS:INT_IN_PROGRESS,0 ; clear int in progress flag
- MOV AX,CS:RETURN_VALUE ; move the return value
- OR AX,AX ;;;;;;;;;;;;;;;;;;; return value ?
- JNZ DONE ;;;;;;;;;;;;;;;;;;; yes, pass it through as keystroke
- JMP CS:LC_SERVICE_INT ;;;;;;; no, fetch the next keystroke
- DONE:
- IRET ; return from interrupt
-
- LC_SERVICE_INT ENDP
-
- ;****************************************************************************
- ; description set up the LC interrupt routines
- ;
- ; INT_INIT -- Hooks into the specified int.
- ; INT_TERM -- Unhooks (restores) the specified int.
- ;
- ; NOTE: INT_INIT must be called be int processing can begin...it saves the
- ; current C environment for use at interrupt time.
- ;;
-
- PUBLIC INT_INIT
- IF LPROG
- INT_INIT PROC FAR
- ELSE
- INT_INIT PROC NEAR
- ENDIF
-
- PUSH DS ; save changed seg regs
- PUSH ES
-
- MOV CS:C_ENVIRONMENT_DS,DS ; save C environment for int time
- MOV CS:C_ENVIRONMENT_ES,ES
- MOV CS:C_ENVIRONMENT_SS,SS
-
- MOV AX,_TOP ; determine int time SP
- MOV BX,_STACK ; get size of STACK ;;;;;;;;;;;;;;;;;;;
- ROR BX,1 ; div by 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- SUB AX,BX ; split it in two ;;;;;;;;;;;;;;;;;;;;;
- MOV CS:C_ENVIRONMENT_SP,AX
-
- MOV AH,READ_INT ; read int vector function
- MOV AL,DOS_INT ; specify DOS service vector
- INT 21H
-
- MOV WORD PTR CS:DOS_SERVICE+2,ES ; save current vector
- MOV WORD PTR CS:DOS_SERVICE,BX
-
- LEA DX,LC_SERVICE_INT ; Use DOS to set new int address
- PUSH CS
- POP DS
- MOV AH,WRITE_INT
- MOV AL,DOS_INT
- INT 21H
-
- ;::::::::::::::::::::::::::::::::::::::::
- ; MOV AX,2F00H ;get C's DTA
- ; INT 21H
- ; MOV WORD PTR CS:C_DTA+2,ES ;save it
- ; MOV WORD PTR CS:C_DTA,BX
- ;
- ; MOV AX,5100H ;get C's PSP
- ; INT 21H
- ; MOV CS:C_PSP,BX ;save it
- ;::::::::::::::::::::::::::::::::::::::::
- POP ES ; restore changed seg regs
- POP DS
- RET
-
- INT_INIT ENDP
-
- ;********************* INT_TERM -- kill ints. *******************************
-
- PUBLIC INT_TERM
- IF LPROG
- INT_TERM PROC FAR
- ELSE
- INT_TERM PROC NEAR
- ENDIF
-
- PUSH DS ; DS gets changed
-
- MOV DS,WORD PTR CS:DOS_SERVICE+2 ; Restore previous DOS service vector
- MOV DX,WORD PTR CS:DOS_SERVICE
- MOV AH,WRITE_INT
- MOV AL,DOS_INT
- INT 21H
-
- POP DS ; restore DS
- RET
- INT_TERM ENDP
-
- ENDPS
- END
-